import { Application, BackendSession } from "pinus";
import { Code } from "../../../consts/code";
import aviator, { Aviator, STATUS } from "../../../games/aviator";
import gameConfig, { GameConfig } from "../../../games/aviator/gameConfig";
import { multiple } from "../../../games/aviator/algorithm";

export default function (app: Application) {
    return new AviatorHandler(app);
}

export class AviatorHandler {
    private _aviator: Aviator
    private _gameConfig: GameConfig
    constructor(private app: Application) {
        this._aviator = aviator(app)
        this._gameConfig = gameConfig(app)
    }

    public async enterRequest(msg: {}, session: BackendSession) {
        const userId = parseInt(session.uid)
        if (this._aviator.loading(userId)) {
            return { code: Code.USER_LOADING, msg: 'error user loading' }
        }
        if (this._aviator.unloading(userId)) {
            return { code: Code.USER_UNLOADING, msg: 'error user unloading' }
        }
        if (this._aviator.canReconnect(userId)) {
            this._aviator.reconnect(userId)
        } else {
            if (!await this._aviator.enter(userId)) {
                return { code: Code.ERROR_ENTER_GAME, msg: 'enter game fail' }
            }
        }
        return { code: Code.OK, data: this._aviator.getContextMines(userId) }
    }

    // 玩家下注
    public async betRequest(msg: { index: number, betCount: number, auto: boolean, multiple: number }, session: BackendSession) {
        // 校验参数
        if (msg.betCount > this._gameConfig.maxBet || msg.betCount < this._gameConfig.minBet) {
            return { code: Code.ERROR_PARAM }
        }
        if (msg.auto && (msg.multiple > this._gameConfig.maxMultiple || msg.multiple < this._gameConfig.minMultiple)) {
            return { code: Code.ERROR_PARAM }
        }
        const userId = parseInt(session.uid)
        // 状态
        if (this._aviator.status !== STATUS.WAIT) {
            return { code: Code.ERROR_STATUS, msg: 'not in bet time' }
        }
        // 下注次数
        if (this._aviator.betTimes(userId) >= 2) {
            return { code: Code.MAX_TIMES, msg: 'bet max times' }
        }
        // 是不是updating中
        if (this._aviator.updating(userId)) {
            return { code: Code.INVALID_BET, msg: 'invalid bet' }
        }
        if (this._aviator.getBet(userId, msg.index)) {
            return { code: Code.ERROR_REPEAT, msg: 'repeat bet' }
        }
        // 是否有足够的钱
        if (this._aviator.getCoin(userId) < msg.betCount) {
            return { code: Code.NOT_ENOUGH_COIN, msg: 'not enough coin' }
        }
        if (!this._aviator.bet(userId, msg.index, msg.betCount, msg.auto, msg.multiple)) {
            return { code: Code.INVALID_BET, msg: 'invalid bet' }
        }
        return { code: Code.OK, data: { coin: this._aviator.getCoin(userId) } }
    }

    // 玩家下注
    public async betMinesRequest(msg: { index: number, betCount: number, mines: number }, session: BackendSession) {
        // 校验参数
        if (msg.betCount > this._gameConfig.maxBet || msg.betCount < this._gameConfig.minBet) {
            return { code: Code.ERROR_PARAM }
        }
        const userId = parseInt(session.uid)
        // 下注次数
        // if (this._aviator.betTimes(userId) >= 2) {
        //     return { code: Code.MAX_TIMES, msg: 'bet max times' }
        // }
        //是否重复下注
        if (this._aviator.getBet(userId, msg.index)) {
            return { code: Code.ERROR_REPEAT, msg: 'repeat bet' }
        }
        //是否有足够的钱
        if (this._aviator.getCoin(userId) < msg.betCount) {
            return { code: Code.NOT_ENOUGH_COIN, msg: 'not enough coin' }
        }
        if (!this._aviator.betMines(userId, msg.index, msg.betCount, msg.mines)) {
            return { code: Code.INVALID_BET, msg: 'invalid bet' }
        }
        return { code: Code.OK, data: { coin: this._aviator.getCoin(userId) } }
    }

    // 玩家点击
    public async clickMinesRequest(msg: { clickPos: number }, session: BackendSession) {
        const userId = parseInt(session.uid)
        // 校验玩家传过来的位置 返回数据
        return { code: Code.OK, data: { minesOrDiamonds: this._aviator.inspectMapPos(msg.clickPos, userId) } }
    }

    // 自动点击
    public async autoClickMinesRequest(msg: { autoClickMap: Array<number>, betNum: number, MinesNum: number }, session: BackendSession) {
        const userId = parseInt(session.uid)
        // 校验玩家传过来的位置 返回数据
        return { code: Code.OK, data: { data: this._aviator.inspectAutoMapPos(msg.autoClickMap, msg.betNum, msg.MinesNum, userId) } }
    }

    // 退出
    public async cancelRequest(msg: { index: number }, session: BackendSession) {
        const userId = parseInt(session.uid)
        if (this._aviator.status !== STATUS.WAIT) {
            return { code: Code.ERROR_STATUS, msg: 'time out!!!' }
        }
        if (!this._aviator.cancel(userId, msg.index)) {
            return { code: Code.BET_NOT_FOUND }
        }
        return { code: Code.OK, data: { coin: this._aviator.getCoin(userId) } }
    }
    // cashout
    public async cashOutRequest(msg: { index: number }, session: BackendSession) {
        const userId = parseInt(session.uid)
        if (this._aviator.status !== STATUS.GAME) {
            return { code: Code.ERROR_STATUS, msg: 'time out!!!' }
        }
        const { success, multiple, cashOut } = this._aviator.cashOut(userId, msg.index)
        if (!success) {
            return { code: Code.CASH_OUT_FAIL }
        } else {
            return { code: Code.OK, data: { multiple: multiple, cashOut: cashOut, coin: this._aviator.getCoin(userId) } }
        }
    }
    // cashout
    public async cashOutMinesRequest(msg: {}, session: BackendSession) {
        const userId = parseInt(session.uid)
        const index = this._aviator.getbetInfo(userId).index
        const { success, multiple, cashOut, mapData, clickMapData } = this._aviator.cashOutMines(userId, index, 0)
        if (!success) {
            return { code: Code.CASH_OUT_FAIL }
        } else {
            return {
                code: Code.OK, data:
                {
                    success: true, index: index, multiple: multiple, cashOut: cashOut,
                    coin: this._aviator.getCoin(userId), mapData: mapData, clickMapData: clickMapData
                }
            }
        }
    }
}
